package com.example.es.service;

import com.example.es.dataobject.ProductPO;
import com.example.es.dataobject.ProductQueryForm;
import com.example.es.repository.ProductRepository;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * es  service方法
 *
 * @author luowj12
 * @since 2021/4/27 15:41
 */
@Service
public class ProductService {
    @Autowired
    private ProductRepository productRepository;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchTemplate;

    public void save(ProductPO product){
        productRepository.save(product);
    }

    /**
     * 这里要注意，如果使用 save 方法来更新的话，必须是全量字段，否则其它字段会被覆盖。
     */
    public void update(ProductPO product) {
        productRepository.save(product);
    }

    /**
     * 根据 ID 编号，删除一条记录
     * @param id
     */
    public void delete(Integer id) {
        productRepository.deleteById(id);
    }


    /**
     * 根据 ID 编号，查询一条记录
     * @param id
     * @return
     */
    public ProductPO selectById(Integer id) {
        Optional<ProductPO> userDO = productRepository.findById(id);
        System.out.println(userDO.isPresent());
        return userDO.orElse(null);
    }

    /**
     * 获取所有的数据。并制定范围
     * @param idList
     * @return
     */
    public List<ProductPO> selectByIds(List<Integer> idList) {
        Iterable<ProductPO> users = productRepository.findAllById(idList);
        List<ProductPO>  list = new ArrayList<>();
        users.forEach(e->list.add(e));
        return list;
    }


    /**
     * 使用 elasticsearchTemplate
     * 对name 和 description 进行模糊查询
     *
     * where name like '%XXX%' and description like '%XXX%'
     * @param form
     * @return
     */
    public List<ProductPO> listProductPO(ProductQueryForm form){
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if(StringUtils.isNotBlank(form.getName())){
            boolQueryBuilder.must(QueryBuilders.wildcardQuery("name", "*"+form.getName()+"*"));
        }
        if(StringUtils.isNotBlank(form.getDescription())){
            boolQueryBuilder.must(QueryBuilders.wildcardQuery("description", "*"+form.getDescription()+"*"));
        }
        NativeSearchQuery query = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder)
                .withPageable(PageRequest.of(Long.valueOf(form.getPageNum()).intValue()-1, Long.valueOf(form.getPageSize()).intValue())).build();
        SearchHits<ProductPO> res = elasticsearchTemplate.search(query, ProductPO.class,
                IndexCoordinates.of(ProductPO.class.getAnnotation(Document.class).indexName())
        );
        long totalCount = res.getTotalHits();
        List<ProductPO> data = res.getSearchHits().stream().map(a -> a.getContent()).collect(Collectors.toList());
        return data;
    }

    /**
     * 使用 elasticsearchTemplate matchQuery进行匹配
     *
     *
     * where sellPoint = XXX and (cid = XXX or (cid =description and categoryName = XXX)) and appName =XXX
     * @param form
     * @return
     */
    public List<ProductPO> listProductPOBy(ProductQueryForm form){
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        MatchQueryBuilder must1= QueryBuilders.matchQuery("sellPoint","便宜");
        query.must(must1);
        BoolQueryBuilder must3 = QueryBuilders.boolQuery();
        MatchQueryBuilder should31 = QueryBuilders.matchQuery("cid",333);
        must3.should(should31);
        BoolQueryBuilder should32 = QueryBuilders.boolQuery();
        MatchQueryBuilder must321 = QueryBuilders.matchQuery("description","公司");
        MatchQueryBuilder must322 = QueryBuilders.matchQuery("categoryName","aaa");
        should32.must(must321).must(must322);
        must3.should(should32);
        query.must(must3);

        BoolQueryBuilder must4 = QueryBuilders.boolQuery();
        MatchQueryBuilder should41 = QueryBuilders.matchQuery("name",form.getName()).boost(3);
        must4.should(should41);
        query.must(must4);

        NativeSearchQuery nquery = new NativeSearchQueryBuilder()
                .withQuery(query)
                .withPageable(PageRequest.of(Long.valueOf(form.getPageNum()).intValue()-1, Long.valueOf(form.getPageSize()).intValue())).build();
        SearchHits<ProductPO> res = elasticsearchTemplate.search(nquery, ProductPO.class,
                IndexCoordinates.of(ProductPO.class.getAnnotation(Document.class).indexName())
        );
        long totalCount = res.getTotalHits();
        List<ProductPO> data = res.getSearchHits().stream().map(a -> a.getContent()).collect(Collectors.toList());
        return data;
    }

}
